home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
ulib
/
interpol.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
4KB
|
189 lines
/***********************************************************************
* $Id: interpol.c,v 0.80 1994/02/24 09:48:11 zhao Exp $
*
*. Copyright(c) 1993,1994 by T.C. Zhao
* All rights reserved.
*.
*
* Interpolate a tabulated function onto a uniform grid using Nth order
* Lagrangian polynomial. deg specifies the degree of interpolating
* polynomial but in practice, deg > 3 is a bad idea.
*
* If we can assume input is uniform grided, Newton's forward difference
* polynomial method can be used, which is faster.
*
***********************************************************************/
#if !defined(lint) && defined(F_ID)
char *id_intpl = "$Id: interpol.c,v 0.80 1994/02/24 09:48:11 zhao Exp $";
#endif
#include "ulib.h"
int
lp_interpol(float *xin, float *yin, int nin, float grid,
float *xout, float *yout, int *nout, int deg)
{
int i, j, k, l, n, jo;
int ih, im, idm;
float term;
/* sanity checks */
if (grid < 0.0 || nin < (deg + 1))
{
M_err("Interpol", "Bad arg grid=%g nin=%d", grid, nin);
return -1;
}
/* points in output */
n = ((xin[nin - 1] - xin[0]) / grid + 0.01) + 1;
if (n > *nout)
{
M_warn("Interpol", "output truncated");
n = *nout;
}
xout[0] = xin[0];
yout[0] = yin[0];
jo = 0;
for (i = 1; i < n; i++)
{
xout[i] = xin[0] + i * grid;
/* center current point using binary search */
j = jo;
ih = nin;
while ((ih - j) > 1)
{
im = (ih + j) / 2;
if (xout[i] > xin[im])
j = im;
else
ih = im;
}
jo = j;
j -= deg / 2;
/* boundary checks */
if (j < 0)
j = 0;
if (j > (nin - deg - 1))
j = nin - deg - 1;
/* do it now */
yout[i] = 0.0;
idm = j + deg;
for (l = j; l <= idm; l++)
{
term = yin[l];
for (k = j; k <= idm; k++)
{
if (l != k)
term *= (xout[i] - xin[k]) / (xin[l] - xin[k]);
}
yout[i] += term;
}
}
*nout = n;
return 0;
}
/*********************************************************************
* A single point
********************************************************************/
float
val_lp_interpol(float *x, float *y, int n, float xval, int deg)
{
float val, term;
int j, l, k;
int ih, im, idm;
if (xval < x[0] || xval > x[n - 1])
{
M_err("ValInterpol", "Failed to bracket %g", x);
return 0.0;
}
/* hunt to center */
j = 0;
ih = n;
while ((ih - j) > 1)
{
im = (ih + j) / 2;
if (xval > x[im])
j = im;
else
ih = im;
}
j -= deg / 2;
/* boundary checks */
if (j < 0)
j = 0;
if (j > (n - deg - 1))
j = n - deg - 1;
/* do it now */
val = 0.0;
idm = j + deg;
for (l = j; l <= idm; l++)
{
term = y[l];
for (k = j; k <= idm; k++)
{
if (l != k)
term *= (xval - x[k]) / (x[l] - x[k]);
}
val += term;
}
return val;
}
#ifdef TEST
#include <stdio.h>
main()
{
float grid = 0.2;
float x[100], y[100];
float inx[30], iny[30];
float *xp = inx, *yp = iny;
int i = 0, nout;
while (scanf(" %f %f ", xp, yp) == 2)
{
xp++;
yp++;
i++;
}
nout = 100;
fprintf(stderr, "NIN=%d\n", i);
#if 0
lp_interpol(inx, iny, i, grid, x, y, &nout, 3);
xp = x;
yp = y;
printf("N=%d\n", nout);
for (i = 0; i < nout; i++, xp++, yp++)
printf("%8.3f %8.3f\n", *xp, *yp);
#else
printf("X=%f Y=%f\n",
3.32, val_lp_interpol(inx, iny, i, 3.32, 3));
#endif
}
#endif